local inCombat = nil
local dndBanner = "<SBW> "

local dndString = dndBanner .. "I'm busy fighting %s (currently at %d%% with %d/%d players alive). You'll be notified when combat ends."
local combatEndedString = dndBanner .. "Combat ended after %d minutes."

do
	local locale = GetLocale()
	if locale == "deDE" then
		dndString = dndBanner .. "Ich bin im Kampf mit %s (noch %d%% Leben with %d/%d players alive). Du wirst nach Kampfende benachrichtigt werden."
		combatEndedString = dndBanner .. "Kampf beendet nach %d Minuten."
	end
end

local whisperers = {}
local combatStart = nil
local boss = nil
local bossHp = nil
local totalElapsed = 0

local pname = UnitName("player")

local bannerTest = "^" .. dndBanner
local function outgoingFilter()
	if arg1:find(bannerTest) then return true end
end

local function incomingFilter()
	if not boss then return end

	if type(arg2) ~= "string" or arg2 == pname or
	  (UnitExists("target") and UnitName("target") == arg2) or UnitInRaid(arg2) or
	  (type(arg6) == "string" and arg6 == "GM") then return end

	if not whisperers[arg2] or whisperers[arg2] == 1 or arg1 == "status" then
		-- Let him know we are fighting a boss
		whisperers[arg2] = 2

		local total = GetNumRaidMembers()
		local alive = 0
		for i = 1, total do
			if not UnitIsDeadOrGhost(GetRaidRosterInfo(i)) then alive = alive + 1 end
		end
		SendChatMessage(dndString:format(boss, bossHp, alive, total), "WHISPER", nil, arg2)
	end
end

ChatFrame_AddMessageEventFilter("CHAT_MSG_WHISPER_INFORM", outgoingFilter)
ChatFrame_AddMessageEventFilter("CHAT_MSG_WHISPER", incomingFilter)

local function checkTarget(id)
	return UnitExists(id) and UnitAffectingCombat(id) and UnitClassification(id) == "worldboss"
end

local function scan()
	if checkTarget("target") then return "target" end
	if checkTarget("focus") then return "focus" end
	if UnitInRaid("player") then
		for i = 1, GetNumRaidMembers() do
			if checkTarget("raid"..i.."target") then return "raid"..i.."target" end
		end
	else
		for i = 1, 5 do
			if checkTarget("party"..i.."target") then return "party"..i.."target" end
		end
	end
end

local frame = CreateFrame("Frame")
local function updateBossTarget()
	local target = scan()
	if not target then return end
	if not boss then
		frame:RegisterEvent("UNIT_HEALTH")
	end
	boss = UnitName(target)
	bossHp = UnitHealth(target)
end

local function onUpdate(self, elapsed)
	totalElapsed = totalElapsed + elapsed
	if totalElapsed > 1 then
		local t = scan()
		if t then totalElapsed = 0; return end
		self:SetScript("OnUpdate", nil)

		local time = GetTime() - combatStart
		local msg = combatEndedString:format(math.floor(time / 60))
		for k, v in pairs(whisperers) do
			-- Notify people that combat has ended
			SendChatMessage(msg, "WHISPER", nil, k)
			whisperers[k] = nil
		end
		combatStart = nil
		if boss then
			self:UnregisterEvent("UNIT_HEALTH")
			boss = nil
			bossHp = nil
		end
		self:UnregisterEvent("PLAYER_TARGET_CHANGED")
	end
end

frame:SetScript("OnEvent", function(self, event, msg)
	if event == "PLAYER_REGEN_DISABLED" then
		local _, t = IsInInstance()
		if t ~= "raid" then return end
		self:RegisterEvent("PLAYER_TARGET_CHANGED")
		self:SetScript("OnUpdate", nil)
		totalElapsed = 0
		combatStart = GetTime()
		updateBossTarget()
	elseif event == "PLAYER_TARGET_CHANGED" then
		updateBossTarget()
	elseif event == "PLAYER_REGEN_ENABLED" then
		if combatStart then
			self:SetScript("OnUpdate", onUpdate)
		end
	elseif event == "UNIT_HEALTH" and msg and UnitName(msg) == boss then
		bossHp = UnitHealth(msg)
		-- Allow new status whispers every 10%
		if bossHp % 10 == 0 then
			for k in pairs(whisperers) do
				whisperers[k] = 1
			end
		end
	end
end)

frame:RegisterEvent("PLAYER_REGEN_DISABLED")
frame:RegisterEvent("PLAYER_REGEN_ENABLED")

